#include "library.h"

library::library(const std::string &database)
{
    dbopen=sqlite3_open(database.c_str(), &db)==SQLITE_OK;
    if (!dbopen)
    {
        std::cout<<"Hiba az adatbazis megnyitasa kozben."<<std::endl;
    }
}

library::~library()
{
    sqlite3_close(db);
}

std::string library::rot13(const std::string &input)
{
    std::string result;
    for (int i=0;i<(int)input.size();++i)
    {
        char c=input.at(i);
        if (c>='a'&&c<='z')
            c=(c-'a'+13)%26+'a';
        else
            if (c>='A'&&c<='Z')
                c=(c-'A'+13)%26+'A';
        result+=c;
    }
    return result;
}

bool library::login()
{
    std::string usr,pswd;
    bool err=true;
    while (err)
    {
        std::cout<<"Kerem a felhasznalonevet:";
        std::getline(std::cin,usr,'\n');
        err=usr.find("'")!=std::string::npos;
    }
    err=true;
    while (err)
    {
        std::cout<<"Kerem a jelszot:";
        std::getline(std::cin,pswd,'\n');
        err=pswd.find("'")!=std::string::npos;
    }
    std::vector<std::string> tmp;
    tmp=SQLQuery("SELECT * FROM librarians WHERE name='"+usr+"' AND PASSWORD='"+rot13(pswd)+"'");
    return tmp.size()!=0;
}

void library::CreateBook(const std::vector<std::string> &data)
{
    book book(data.at(0),data.at(1),data.at(2),atoi(data.at(3).c_str()),atoi(data.at(4).c_str()),data.at(5));
    std::stringstream ss;
    std::string year,edition;
    ss<<book.GetYear();
    year=ss.str();
    ss.str("");
    ss<<book.GetEdition();
    edition=ss.str();
    SQLQuery("INSERT INTO books(Author,Title,Publisher,Year,Edition,ISBN,Loanable)VALUES('"+book.GetAuthor()+"','"+book.GetTitle()+"','"+book.GetPublisher()+"','"+year+"','"+edition+"','"+book.GetISBN()+"',1)");
}

void library::ListBooks()
{
    std::vector<std::string> tmp;
    tmp=SQLQuery("SELECT * FROM books");
    for(int i=0;i<(int)tmp.size();++i)
        {
            std::stringstream ss(tmp.at(i));
            std::string tmp2;
            for (int i=0;i<7;++i)
            {
                std::getline(ss,tmp2,'|');
                std::cout<<tmp2<<'\t';
            }
            std::cout<<std::endl;
        }
}

void library::Querybooks(const std::string &query)
{
    std::vector<std::string> tmp;
    std::string query_l;
    for (int i=0;i<(int)query.size();++i)
        query_l+=tolower(query.at(i));
    tmp=SQLQuery("SELECT * FROM books WHERE Title LIKE '%"+query_l+"%'");
    for(int i=0;i<(int)tmp.size();++i)
        {
            std::stringstream ss(tmp.at(i));
            std::string tmp2;
            for (int i=0;i<7;++i)
            {
                std::getline(ss,tmp2,'|');
                std::cout<<tmp2<<'\t';
            }
            std::cout<<std::endl;
        }
}

void library::DeleteBook(int id)
{
    std::stringstream ss;
    std::string bid;
    std::vector<std::string> tmp;
    ss<<id;
    bid=ss.str();
    tmp=SQLQuery("SELECT * FROM books WHERE BookId="+bid);
    if (tmp.size()!=0)
    {
        SQLQuery("DELETE FROM books WHERE BookId="+bid);
    } else
        std::cout<<"Nem letezik ilyen id-ju konyv."<<std::endl;
}

void library::LoanBook(int bookID,int userID,std::string begin)
{
    std::stringstream ss;
    std::string bid;
    std::string uid;
    std::vector<std::string> tmp;
    bool loanable=false;
    ss<<bookID;
    bid=ss.str();
    ss.str("");
    ss<<userID;
    uid=ss.str();
    tmp=SQLQuery("SELECT * FROM books WHERE BookId="+bid);
    if (tmp.size()==1)
    {
        loanable=tmp.at(0).at(tmp.at(0).length()-2)=='1';
        if (loanable)
        {
            tmp=SQLQuery("SELECT * FROM users WHERE UserId="+uid);
            if (tmp.size()==1)
            {
                loan loan(bookID,userID,begin);
                std::stringstream ss;
                std::string uid;
                std::string bid;
                ss<<loan.GetUserID();
                uid=ss.str();
                ss.str("");
                ss<<loan.GetBookID();
                bid=ss.str();
                SQLQuery("INSERT INTO loans(UserID,BookID,Begin,End,Returned)VALUES("+uid+","+bid+",'"+loan.GetBeginDate()+"','"+loan.GetEndDate()+"',0)");
            } else
                std::cout<<"Nem letezik ilyen id-ju tag."<<std::endl;
        } else
            std::cout<<"Ezt a konyvet mar kikolcsonoztek."<<std::endl;
    } else
        std::cout<<"Nem letezik ilyen id-ju konyv."<<std::endl;
}

void library::ReturnBook(int id)
{
    std::stringstream ss;
    std::string bid;
    std::vector<std::string> tmp;
    bool loanable=false;
    ss<<id;
    bid=ss.str();
    tmp=SQLQuery("SELECT * FROM books WHERE BookId="+bid);
    if (tmp.size()==1)
    {
        loanable=tmp.at(0).at(tmp.at(0).length()-2)=='1';
        if (!loanable)
        {

        } else
            std::cout<<"Ezt a konyvet nem kolcsonoztek ki."<<std::endl;
    } else
        std::cout<<"Nem letezik ilyen id-ju konyv."<<std::endl;
}

void library::CreateUser(const std::vector<std::string> &data)
{
    user *tmp;
    std::string type;
    switch (atoi(data.at(0).c_str()))
    {
        case 1:
            //1 - egyetemi polgar
            tmp=new citizen(data.at(1),data.at(2),data.at(3));
        break;
        case 2:
            //2 - egyetemi oktato
            tmp=new tutor(data.at(1),data.at(2),data.at(3));
        break;
        case 3:
            //3 - mas egyetem polgara
            tmp=new foreigncitizen(data.at(1),data.at(2),data.at(3));
        break;
        case 4:
            //4 - vendeg
            tmp=new guest(data.at(1),data.at(2),data.at(3));
        break;
    }
    std::stringstream ss;
    ss<<tmp->GetType();
    type=ss.str();
    SQLQuery("INSERT INTO users(Type,Name,Address,Contact)VALUES("+type+",'"+tmp->GetName()+"','"+tmp->GetAddress()+"','"+tmp->GetContact()+"')");
}

void library::ListUsers()
{
    std::vector<std::string> tmp;
    tmp=SQLQuery("SELECT * FROM users");
    for(int i=0;i<(int)tmp.size();++i)
        {
            std::stringstream ss(tmp.at(i));
            std::string tmp2;
            for (int i=0;i<5;++i)
            {
                std::getline(ss,tmp2,'|');
                if (i==3)
                {
                    switch (atoi(tmp2.c_str()))
                    {
                        case 1:
                            std::cout<<"Egyetemi polgar\t";
                        break;
                        case 2:
                            std::cout<<"Egyetemi oktato\t";
                        break;
                        case 3:
                            std::cout<<"Mas egyetem polgara\t";
                        break;
                        case 4:
                            std::cout<<"Vendeg\t";
                        break;
                    }
                }
                else
                    std::cout<<tmp2<<'\t';
            }
            std::cout<<std::endl;
        }
}

void library::ModifyUser(const std::vector<std::string> &data)
{
    std::vector<std::string> tmp;
    std::string uid;
    tmp=SQLQuery("SELECT * FROM users WHERE UserId="+data.at(0));
    if (tmp.size()==1)
    {
        std::stringstream ss(tmp.at(0));
        std::string tmp2,name,address,type,contact;
        std::getline(ss,tmp2,'|');
        std::getline(ss,tmp2,'|');
        name=tmp2;
        std::getline(ss,tmp2,'|');
        contact=tmp2;
        std::getline(ss,tmp2,'|');
        type=tmp2;
        std::getline(ss,tmp2,'|');
        address=tmp2;
        menu menu;
        bool err=true;
        std::string ntype,nname,naddress,ncontact;
        std::stringstream ss2;
        std::getline(std::cin,nname,'\n');
        while (err)
        {
            std::cout<<"Kerem a tag uj tipusat (1 - egyetemi polgar, 2 - egyetemi oktato, 3 - mas egyetem polgara, 4 - vendeg)("+type+"):";
            err=menu.input(ntype);
            err=err||atoi(ntype.c_str())<1||atoi(ntype.c_str())>4;
        }
        err=true;
        while (err)
        {
            std::cout<<"Kerem a tag uj nevet ("+name+"):";
            err=menu.input(nname);
        }
        err=true;
        while (err)
        {
            std::cout<<"Kerem a tag uj cimet ("+address+"):";
            err=menu.input(naddress);
        }
        err=true;
        while (err)
        {
            std::cout<<"Kerem a tag uj elerhetoseget ("+contact+"):";
            err=menu.input(ncontact);
        }
        user *tmp;
        switch (atoi(ntype.c_str()))
        {
            case 1:
                //1 - egyetemi polgar
                tmp=new citizen(nname,naddress,ncontact);
            break;
            case 2:
                //2 - egyetemi oktato
                tmp=new tutor(nname,naddress,ncontact);
            break;
            case 3:
                //3 - mas egyetem polgara
                tmp=new foreigncitizen(nname,naddress,ncontact);
            break;
            case 4:
                //4 - vendeg
                tmp=new guest(nname,naddress,ncontact);
            break;
        }
        std::stringstream ss3;
        ss3<<tmp->GetType();
        ntype=ss3.str();
        SQLQuery("UPDATE users SET Type="+ntype+",Name='"+tmp->GetName()+"',Address='"+tmp->GetAddress()+"',Contact='"+tmp->GetContact()+"' WHERE UserId="+data.at(0));
    }
    else
        std::cout<<"Nincs ilyen ID-ju tag."<<std::endl;
}
void library::ListUserLoans(int id)
{
    std::stringstream ss;
    std::string uid;
    std::vector<std::string> tmp;
    ss<<id;
    uid=ss.str();
    tmp=SQLQuery("SELECT * FROM loans WHERE UserID="+uid);
    for(int i=0;i<(int)tmp.size();++i)
        {
            std::stringstream ss(tmp.at(i));
            std::string tmp2;
            for (int i=0;i<5;++i)
            {
                std::getline(ss,tmp2,'|');
                if (i==1)
                {
                    std::vector<std::string> tmp3;
                    std::string tmp4;
                    tmp3=SQLQuery("SELECT * FROM books WHERE BookID="+tmp2);
                    std::stringstream ss2(tmp3.at(0));
                    for (int i=0;i<3;++i)
                        std::getline(ss2,tmp4,'|');
                    std::cout<<tmp4<<"\t";
                }
                else
                    if (i!=2)
                        std::cout<<tmp2<<"\t";
            }
            std::getline(ss,tmp2,'|');
            if (tmp2=="1")
                std::cout<<"visszahozva";
            else
                std::cout<<"kolcsonozve";
            std::cout<<std::endl;
        }
}

void library::DeleteUser(int id)
{
    std::stringstream ss;
    std::string uid;
    std::vector<std::string> tmp;
    ss<<id;
    uid=ss.str();
    tmp=SQLQuery("SELECT * FROM users WHERE UserId="+uid);
    if (tmp.size()!=0)
    {
        SQLQuery("DELETE FROM users WHERE UserId="+uid);
    } else
        std::cout<<"Nem letezik ilyen id-ju tag."<<std::endl;
}

void library::run()
{
    if (dbopen)
    {
        if (login())
        {
            menu menu;
            MenuResult result=menu.print();
            while (result.choice!=12)
            {
                switch (result.choice)
                {
                    case 1:
                    //1.Konyv felvetele
                        CreateBook(result.params);
                    break;
                    case 2:
                    //2.Konyv(ek) listazasa
                        ListBooks();
                    break;
                    case 3:
                    //3.Konyv(ek) keresese
                        Querybooks(result.params.at(0));
                    break;
                    case 4:
                    //4.Konyv torlese
                        DeleteBook(atoi(result.params.at(0).c_str()));
                    break;
                    case 5:
                    //5.Konyv kolcsonzese
                        LoanBook(atoi(result.params.at(0).c_str()),atoi(result.params.at(1).c_str()),result.params.at(2));
                    break;
                    case 6:
                    //6.Konyv visszahozatala
                        ReturnBook(atoi(result.params.at(0).c_str()));
                    break;
                    case 7:
                    //7.Tag felvetele
                        CreateUser(result.params);
                    break;
                    case 8:
                    //8.Tag(ok) listazasa
                        ListUsers();
                    break;
                    case 9:
                    //9.Tag modositasa
                        ModifyUser(result.params);
                    break;
                    case 10:
                    //10.Tag kolcsonzeseinek listazasa
                        ListUserLoans(atoi(result.params.at(0).c_str()));
                    break;
                    case 11:
                    //11.Tag torlese
                        DeleteUser(atoi(result.params.at(0).c_str()));
                    break;
                }
                result=menu.print();
            }
        } else
            std::cout<<"Hibas felhasznalonev vagy jelszo."<<std::endl;
    }
}

std::vector<std::string> library::SQLQuery(const std::string &query)
{
    std::vector<std::string> result;
    sqlite3_stmt *st;
    if(sqlite3_prepare(db,query.c_str(),-1,&st,0)==SQLITE_OK)
    {
        int col=sqlite3_column_count(st);
        int res=0;
        while (res!=SQLITE_DONE)
        {
            res=sqlite3_step(st);
            if(res==SQLITE_ROW)
            {
                std::string tmp;
                for(int i=0;i<col;++i)
                    tmp=tmp+(char*)sqlite3_column_text(st, i)+"|";
                result.push_back(tmp);
            }
        }
        sqlite3_finalize(st);
    }
    return result;
}
